package cell;

import java.util.Comparator;
import java.util.Map;

import ants.Direction;
import ants.GameState;

import com.google.common.base.Function;

/**
 * Represents a (row, col) location on the game map.
 * 
 * Is a token; it can't be changed in any way once created.
 * 
 * No longer implements Comparable<MapLocation>. Now has its own Comparator,
 * which allows one to build a sortValueMap, which is consulted for comparison
 * purposes. Otherwise orders by hashCode, which strings the cells out in
 * row-order.
 * 
 */
public class Cell {
  
  
  public static class CellComparator implements Comparator<Cell> {
    
    private final Map<Cell, Double> sortValueMap;
    
    
    public CellComparator(Map<Cell, Double> sortValueMap) {
      this.sortValueMap = sortValueMap;
    }
    
    
    @Override
    public int compare(Cell cell_1, Cell cell_2) {
      if (cell_1.equals(cell_2)) return 0;
      
      final double sortValue1 = sortValueMap.get(cell_1);
      final double sortValue2 = sortValueMap.get(cell_2);
      
      return (int) Math.signum(sortValue1 != sortValue2 ? sortValue1 - sortValue2
                                                       : cell_1.hashCode( ) - cell_2.hashCode( ));
    }
  }
  
  
  public final int                 col;
  
  public final int                 row;
  
  
  public Function<Direction, Cell> takeAStepFunction = new Function<Direction, Cell>( ) {
                                                       
                                                       @Override
                                                       public Cell apply(Direction dir) {
                                                         return dir.takeAStep(Cell.this);
                                                       }
                                                     };
  
  
  public Cell(Cell cell) {
    this(cell.row, cell.col);
  }
  
  
  public Cell(double row, double col) {
    this((int) Math.round(row), (int) Math.round(col));
  }
  
  
  public Cell(int row, int col) {
    this.row = row;
    this.col = col;
  }
  
  
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean equals(Object o) {
    return o instanceof Cell
           && row == ((Cell) o).row
           && col == ((Cell) o).col;
  }
  
  
  /**
   * {@inheritDoc}
   */
  @Override
  public int hashCode( ) {
    return row * GameState.cols + col;
  }
  
  
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString( ) {
    return getClass( ).getSimpleName( ) + "(" + row + ", " + col + ")";
  }
  
  
  /**
   * A version of toString that adds information from the gameState.
   */
  public String toString(GameState gameState) {
    return toString( ) + gameState.getCellProperties(this);
  }
  
}
